import AppError from "@/shared/app-error";
import { User } from "@prisma/client";
import _ from "lodash";
import db from "@/server/connector/db";

type SessionOptions = {
  base: BaseAuthInfo;
};

type BaseAuthInfo = { authed: true; userId: string; sessionId: string } | { authed: false };
type InMemoryCache = { user: User | null };

export default class Session {
  #base: BaseAuthInfo;
  #cache: InMemoryCache;

  constructor({ base }: SessionOptions) {
    this.#base = base;
    this.#cache = { user: null };
  }

  get authenticated(): boolean {
    return this.#base.authed;
  }

  get userId$(): string | null {
    return this.#base.authed ? this.#base.userId : null;
  }

  async getMe(): Promise<User> {
    const me = await this.getMe$();
    if (!me) {
      throw AppError.unauthError();
    }
    return me;
  }

  async getMe$(): Promise<User | null> {
    if (this.#cache.user) {
      return this.#cache.user;
    }

    const userId = this.userId$;
    if (userId) {
      const user = await db.user.findUnique({ where: { id: userId } });
      this.#cache.user = user;
    }
    return this.#cache.user;
  }
}
